//! 数据填充逻辑实现

use std::collections::HashMap;
use std::time::{Duration, Instant};
use serde_json::Value;
use crate::error::{DataForgeError, Result};
use crate::schema::TableSchema;
use super::{DatabaseFiller, FillingConfig, FillingStats, ConnectionManager};

/// 数据填充执行器
pub struct FillingExecutor {
    connection_manager: ConnectionManager,
    config: FillingConfig,
    stats: FillingStats,
}

impl FillingExecutor {
    /// 创建新的填充执行器
    pub fn new(connection_manager: ConnectionManager, config: FillingConfig) -> Self {
        Self {
            connection_manager,
            config,
            stats: FillingStats::default(),
        }
    }

    /// 执行完整的数据填充流程
    pub fn execute_filling(&mut self, schema: &TableSchema, data: Vec<HashMap<String, Value>>) -> Result<()> {
        let start_time = Instant::now();
        
        // 重置统计信息
        self.stats = FillingStats::default();
        self.stats.total_rows = data.len();

        // 创建表
        self.create_table(schema)?;

        // 批量插入数据
        self.batch_insert(&schema.name, data)?;

        // 更新统计信息
        self.stats.processing_time_ms = start_time.elapsed().as_millis() as u64;
        self.stats.calculate_speed();

        Ok(())
    }

    /// 执行数据填充（带重试机制）
    pub fn execute_with_retry(&mut self, schema: &TableSchema, data: Vec<HashMap<String, Value>>) -> Result<()> {
        let mut last_error = None;
        
        for attempt in 0..=self.config.retry_count {
            match self.execute_filling(schema, data.clone()) {
                Ok(()) => return Ok(()),
                Err(e) => {
                    last_error = Some(e);
                    if attempt < self.config.retry_count {
                        // 等待一段时间后重试
                        std::thread::sleep(Duration::from_millis(1000 * (attempt + 1) as u64));
                    }
                }
            }
        }

        Err(last_error.unwrap_or_else(|| DataForgeError::generator("Unknown error during retry")))
    }

    /// 分块处理大量数据
    pub fn execute_chunked(&mut self, schema: &TableSchema, data: Vec<HashMap<String, Value>>) -> Result<()> {
        let start_time = Instant::now();
        
        // 重置统计信息
        self.stats = FillingStats::default();
        self.stats.total_rows = data.len();

        // 创建表
        self.create_table(schema)?;

        // 分块处理数据
        let chunks: Vec<_> = data.chunks(self.config.batch_size).collect();
        
        for (i, chunk) in chunks.iter().enumerate() {
            match self.insert_data(&schema.name, chunk.to_vec()) {
                Ok(()) => {
                    self.stats.successful_rows += chunk.len();
                }
                Err(e) => {
                    self.stats.failed_rows += chunk.len();
                    eprintln!("Failed to insert chunk {}: {}", i, e);
                }
            }
        }

        // 更新统计信息
        self.stats.processing_time_ms = start_time.elapsed().as_millis() as u64;
        self.stats.calculate_speed();

        Ok(())
    }

    /// 验证数据完整性
    pub fn validate_data(&self, data: &[HashMap<String, Value>], schema: &TableSchema) -> Result<Vec<String>> {
        let mut errors = Vec::new();

        for (index, row) in data.iter().enumerate() {
            // 检查必需字段
            for field in &schema.fields {
                if !field.constraints.nullable && !row.contains_key(&field.name) {
                    errors.push(format!("Row {}: Missing required field '{}'", index, field.name));
                }
            }

            // 检查唯一性约束（简单检查，实际应该查询数据库）
            for field in &schema.fields {
                if field.constraints.unique {
                    if let Some(value) = row.get(&field.name) {
                        if value.is_null() && !field.constraints.nullable {
                            errors.push(format!("Row {}: Unique field '{}' cannot be null", index, field.name));
                        }
                    }
                }
            }

            // 检查数据类型
            for (field_name, value) in row {
                if let Some(field) = schema.fields.iter().find(|f| f.name == *field_name) {
                    if let Err(e) = self.validate_field_value(value, field) {
                        errors.push(format!("Row {}: Field '{}' - {}", index, field_name, e));
                    }
                }
            }
        }

        Ok(errors)
    }

    /// 验证字段值
    fn validate_field_value(&self, value: &Value, field: &crate::schema::FieldSchema) -> Result<()> {
        use crate::schema::DataType;

        match (&field.data_type, value) {
            (DataType::String { max_length }, Value::String(s)) => {
                if let Some(max_len) = max_length {
                    if s.len() > *max_len {
                        return Err(DataForgeError::validation(&format!(
                            "String length {} exceeds maximum {}", s.len(), max_len
                        )));
                    }
                }
            },
            (DataType::Integer { min, max }, Value::Number(n)) => {
                if let Some(i) = n.as_i64() {
                    if let Some(min_val) = min {
                        if i < *min_val {
                            return Err(DataForgeError::validation(&format!(
                                "Integer {} is less than minimum {}", i, min_val
                            )));
                        }
                    }
                    if let Some(max_val) = max {
                        if i > *max_val {
                            return Err(DataForgeError::validation(&format!(
                                "Integer {} exceeds maximum {}", i, max_val
                            )));
                        }
                    }
                } else {
                    return Err(DataForgeError::validation("Expected integer value"));
                }
            },
            (DataType::Email, Value::String(s)) => {
                if !s.contains('@') || !s.contains('.') {
                    return Err(DataForgeError::validation("Invalid email format"));
                }
            },
            (DataType::Phone { .. }, Value::String(s)) => {
                if s.is_empty() || s.len() > 20 {
                    return Err(DataForgeError::validation("Invalid phone number format"));
                }
            },
            _ => {} // 其他类型的验证可以在这里添加
        }

        Ok(())
    }

    /// 生成插入SQL语句
    fn generate_insert_sql(&self, table_name: &str, data: &[HashMap<String, Value>]) -> Result<String> {
        if data.is_empty() {
            return Err(DataForgeError::validation("No data to insert"));
        }

        let first_row = &data[0];
        let columns: Vec<&String> = first_row.keys().collect();
        
        let mut sql = format!("INSERT INTO {} (", table_name);
        sql.push_str(&columns.iter().map(|c| c.as_str()).collect::<Vec<_>>().join(", "));
        sql.push_str(") VALUES ");

        let value_clauses: Vec<String> = data.iter().map(|row| {
            let values: Vec<String> = columns.iter().map(|col| {
                match row.get(*col) {
                    Some(Value::String(s)) => format!("'{}'", s.replace("'", "''")),
                    Some(Value::Number(n)) => n.to_string(),
                    Some(Value::Bool(b)) => if *b { "TRUE" } else { "FALSE" }.to_string(),
                    Some(Value::Null) | None => "NULL".to_string(),
                    Some(other) => format!("'{}'", other.to_string().replace("'", "''")),
                }
            }).collect();
            format!("({})", values.join(", "))
        }).collect();

        sql.push_str(&value_clauses.join(", "));
        Ok(sql)
    }
}

impl DatabaseFiller for FillingExecutor {
    fn create_table(&mut self, schema: &TableSchema) -> Result<()> {
        // 这里应该执行实际的SQL创建表语句
        // 由于我们没有实际的数据库连接，这里只做模拟
        println!("Creating table: {}", schema.name);
        Ok(())
    }

    fn insert_data(&mut self, table_name: &str, data: Vec<HashMap<String, Value>>) -> Result<()> {
        if data.is_empty() {
            return Ok(());
        }

        // 生成SQL语句
        let _sql = self.generate_insert_sql(table_name, &data)?;
        
        // 这里应该执行实际的SQL插入语句
        // 由于我们没有实际的数据库连接，这里只做模拟
        println!("Inserting {} rows into table: {}", data.len(), table_name);
        
        self.stats.successful_rows += data.len();
        Ok(())
    }

    fn batch_insert(&mut self, table_name: &str, data: Vec<HashMap<String, Value>>) -> Result<()> {
        let chunks: Vec<_> = data.chunks(self.config.batch_size).collect();
        
        for chunk in chunks {
            self.insert_data(table_name, chunk.to_vec())?;
        }
        
        Ok(())
    }

    fn get_stats(&self) -> FillingStats {
        self.stats.clone()
    }

    fn truncate_table(&mut self, table_name: &str) -> Result<()> {
        // 这里应该执行实际的TRUNCATE语句
        println!("Truncating table: {}", table_name);
        Ok(())
    }

    fn drop_table(&mut self, table_name: &str) -> Result<()> {
        // 这里应该执行实际的DROP TABLE语句
        println!("Dropping table: {}", table_name);
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::filling::ConnectionConfig;
    use crate::schema::{FieldSchema, FieldConstraints, DataType};

    fn create_test_schema() -> TableSchema {
        TableSchema {
            name: "test_table".to_string(),
            fields: vec![
                FieldSchema {
                    name: "id".to_string(),
                    data_type: DataType::Integer { min: None, max: None },
                    constraints: FieldConstraints {
                        nullable: false,
                        unique: true,
                        default: None,
                        pattern: None,
                        min: None,
                        max: None,
                    },
                    description: None,
                    generator_config: None,
                },
                FieldSchema {
                    name: "name".to_string(),
                    data_type: DataType::String { max_length: Some(100) },
                    constraints: FieldConstraints {
                        nullable: false,
                        unique: false,
                        default: None,
                        pattern: None,
                        min: None,
                        max: None,
                    },
                    description: None,
                    generator_config: None,
                },
            ],
            primary_key: Some(vec!["id".to_string()]),
            indexes: vec![],
            description: None,
        }
    }

    fn create_test_data() -> Vec<HashMap<String, Value>> {
        vec![
            {
                let mut row = HashMap::new();
                row.insert("id".to_string(), Value::Number(serde_json::Number::from(1)));
                row.insert("name".to_string(), Value::String("Alice".to_string()));
                row
            },
            {
                let mut row = HashMap::new();
                row.insert("id".to_string(), Value::Number(serde_json::Number::from(2)));
                row.insert("name".to_string(), Value::String("Bob".to_string()));
                row
            },
        ]
    }

    #[test]
    fn test_filling_executor_creation() {
        let config = ConnectionConfig::sqlite("test.db");
        let connection_manager = ConnectionManager::new(config).unwrap();
        let filling_config = FillingConfig::default();
        
        let executor = FillingExecutor::new(connection_manager, filling_config);
        assert_eq!(executor.stats.total_rows, 0);
    }

    #[test]
    fn test_validate_data() {
        let config = ConnectionConfig::sqlite("test.db");
        let connection_manager = ConnectionManager::new(config).unwrap();
        let filling_config = FillingConfig::default();
        let executor = FillingExecutor::new(connection_manager, filling_config);
        
        let schema = create_test_schema();
        let data = create_test_data();
        
        let errors = executor.validate_data(&data, &schema).unwrap();
        assert!(errors.is_empty());
    }

    #[test]
    fn test_generate_insert_sql() {
        let config = ConnectionConfig::sqlite("test.db");
        let connection_manager = ConnectionManager::new(config).unwrap();
        let filling_config = FillingConfig::default();
        let executor = FillingExecutor::new(connection_manager, filling_config);
        
        let data = create_test_data();
        let sql = executor.generate_insert_sql("test_table", &data).unwrap();
        
        assert!(sql.contains("INSERT INTO test_table"));
        assert!(sql.contains("VALUES"));
        assert!(sql.contains("Alice"));
        assert!(sql.contains("Bob"));
    }
}